package com.jrx.anytxn.transaction.job.dailyAccount.step;

import com.jrx.anytxn.common.uitl.SeqUtils;
import com.jrx.anytxn.common.uitl.StringUtils;
import com.jrx.anytxn.feign.common.GateWayPredicate;
import com.jrx.anytxn.feign.gateway.response.CoreResponse16;
import com.jrx.anytxn.feign.gateway.service.IInnerGatewayService;
import com.jrx.anytxn.param.entity.PrOrganizationTable;
import com.jrx.anytxn.param.service.system.IOrganizationTableService;
import com.jrx.anytxn.transaction.constant.TransBizConstant;
import com.jrx.anytxn.transaction.entity.BtDailyAccountList;
import com.jrx.anytxn.transaction.entity.TlDailyAccountLog;
import com.jrx.anytxn.transaction.entity.TlDisbursementLog;
import com.jrx.anytxn.transaction.job.dailyAccount.bean.DailyAccountBean;
import com.jrx.anytxn.transaction.enums.DailyAccountEnum;
import com.jrx.anytxn.transaction.mapper.ext.ExtBtDailyAccountListMapper;
import com.jrx.anytxn.transaction.pojo.DailyAccount;
import com.jrx.anytxn.transaction.service.IDealGatewayService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 日终T24核心汇总记账逻辑处理
 *
 * @Author yhy
 * @Date 2023/4/29 16:44
 */
@Service
public class DailyAccountProcessor implements ItemProcessor<DailyAccount, DailyAccountBean> {

    private Logger logger = LoggerFactory.getLogger(DailyAccountProcessor.class);

    @Lazy
    @Autowired
    private IInnerGatewayService innerGatewayService;

    @Autowired
    private IDealGatewayService dealGatewayService;

    @Resource
    private ExtBtDailyAccountListMapper extBtDailyAccountListMapper;

    @Autowired
    private IOrganizationTableService organizationTableService;

    @Override
    public DailyAccountBean process(DailyAccount item) throws Exception {
        try {
            String creditMediumAcctCode = null;
            String settleChannels = null;
            // 获取兴安借-他行卡放款内部账户-大小额渠道
            if (DailyAccountEnum.T24_CHANNEL_BEPS_HVPS.getCode().contains(item.getSettleChannel())){
                creditMediumAcctCode = TransBizConstant.OUTER_BANK_DISBURSE_LS_ACCT;
                settleChannels = DailyAccountEnum.T24_CHANNEL_BEPS_HVPS.getCode();
            }
            // 获取兴安借-他行卡放款内部账户-超级网银渠道
            if (DailyAccountEnum.T24_CHANNEL_IBPS.getCode().contains(item.getSettleChannel())){
                creditMediumAcctCode = TransBizConstant.OUTER_BANK_DISBURSE_SUPER_ACCT;
                settleChannels = DailyAccountEnum.T24_CHANNEL_IBPS.getCode();
            }
            DailyAccountBean dailyAccountBean = new DailyAccountBean();
            // 判断借方介质账号码值是否为空
            if (StringUtils.isNotBlank(creditMediumAcctCode)){
                if (BigDecimal.ZERO.compareTo(item.getTotalAmount()) == 0) {
                    return this.buildDailyAccountBean(SeqUtils.getSN(), TransBizConstant.DISBURSEMENT_LOG_SUM_STATUS_S, "0000", "轧差为后金额为0", settleChannels, null, item.getTotalAmount());
                }
                // 发起日终T24核心汇总记账
                dailyAccountBean = this.interestCompensateT24(item, creditMediumAcctCode, settleChannels);
            }
            return dailyAccountBean;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("DailyAccountProcessor 出错了：{}", e);
        }
        return null;
    }

    /**
     * 日终T24核心汇总记账
     * @param record 待记账信息
     * @param creditMediumAcctCode 贷方介质账号码值
     * @param settleChannels 记账渠道列表
     * @return
     * @throws Exception
     */
    private DailyAccountBean interestCompensateT24(DailyAccount record, String creditMediumAcctCode, String settleChannels) throws Exception{
        // 设置记账请求流水号
        String seqNo = SeqUtils.getSN();
        // 构建日终T24核心汇总记账请求信息
        String coreRequest16Json = dealGatewayService.buildT24Req(record, creditMediumAcctCode, seqNo);
        // 调用日终T24核心汇总记账
        GateWayPredicate<CoreResponse16> core16Pre = () -> innerGatewayService.interestCompensate(coreRequest16Json);
        CoreResponse16 res = null;
        try {
            res = core16Pre.getRes(core16Pre);
        } catch (Exception e) {
            logger.error("调用日终T24核心汇总记账接口出现异常", e);
        }

        String transactionId = null;
        String busCode = null;
        String busMsg = null;
        String result = TransBizConstant.DISBURSEMENT_LOG_SUM_STATUS_O;
        if (!ObjectUtils.isEmpty(res)){
            result = res.getDealState();
            busCode = res.getBusCode();
            busMsg = res.getBusMsg();
            transactionId = res.getTransactionId25();
            if (TransBizConstant.GATEWAY_DEAL_SUC.equals(result)) { //成功
                result = TransBizConstant.DISBURSEMENT_LOG_SUM_STATUS_S;
            } else if (TransBizConstant.GATEWAY_DEAL_FAIL.equals(result)) {//失败
                result = TransBizConstant.DISBURSEMENT_LOG_SUM_STATUS_F;
            }
        }
        return this.buildDailyAccountBean(seqNo, result, busCode, busMsg, settleChannels, transactionId, record.getTotalAmount());
    }

    /**
     * 构建日终T24核心汇总记账处理对象
     * @param seqNo 记账请求流水号
     * @param result 交易状态
     * @param busCode 交易返回码
     * @param busMsg 交易返回信息
     * @param settleChannels 记账渠道列表
     * @param transactionId 交易参考号(核心/支付返回)
     * @param totalAmount 汇总金额
     * @return
     */
    private DailyAccountBean buildDailyAccountBean(String seqNo, String result, String busCode, String busMsg,
                                                   String settleChannels, String transactionId, BigDecimal totalAmount){
        DailyAccountBean dailyAccountBean = new DailyAccountBean();
        List<BtDailyAccountList> items = extBtDailyAccountListMapper.selectBySettleChannel(Arrays.asList(settleChannels.split(",")));
        // 过滤标志
        int flag = BigDecimal.ZERO.compareTo(totalAmount);
        List<BtDailyAccountList> list = new ArrayList<>();
        // 轧差为0的情况
        if (flag == 0) {
            list.addAll(items);
        } else {
            list.addAll(items.stream().filter(bt -> BigDecimal.ZERO.compareTo(bt.getAmount()) == flag).collect(Collectors.toList()));
        }
        if(CollectionUtils.isNotEmpty(list)){
            // 切完日后取today
            PrOrganizationTable org = organizationTableService.findByOrgIdForBatch(TransBizConstant.DEFAULT_ORG_ID);
            Date businessDate = org.getToday();

            List<TlDailyAccountLog> accountLogList = new ArrayList<>();
            List<TlDisbursementLog> disLogList = new ArrayList<>();
            for (BtDailyAccountList btDailyAccountList : list){
                // 构建日终T24核心汇总记账明细
                TlDailyAccountLog accountLog = this.buildTlDailyAccountLog(btDailyAccountList, seqNo, result,
                        busCode, busMsg, transactionId, businessDate);
                accountLogList.add(accountLog);

                // 构建放款流水记账信息
                TlDisbursementLog disbursementLog = this.buildTlDisbursementLog(btDailyAccountList, result);
                disLogList.add(disbursementLog);
            }
            dailyAccountBean.setTlDailyAccountLogList(accountLogList);
            dailyAccountBean.setTlDisbursementLogList(disLogList);
        }
        return dailyAccountBean;
    }

    /**
     * 构建日终T24核心汇总记账明细
     * @param record 记账初始化信息
     * @param seqNo 记账请求流水号
     * @param result 交易状态
     * @param busCode 交易返回码
     * @param busMsg 交易返回信息
     * @param transactionId 交易参考号(核心/支付返回)
     * @param businessDate 当前业务日期
     * @return
     */
    private TlDailyAccountLog buildTlDailyAccountLog(BtDailyAccountList record, String seqNo, String result,
                                                     String busCode, String busMsg, String transactionId, Date businessDate){
        TlDailyAccountLog accountLog = new TlDailyAccountLog();
        accountLog.setDisId(record.getId());// 放款流水表id
        accountLog.setTenantId(record.getTenantId());// 租戶id
        accountLog.setOrganizationId(record.getOrganizationId());// 机构号
        accountLog.setChannel(record.getChannel());// 渠道
        accountLog.setProductId(record.getProductId());// 产品id
        accountLog.setCustomerId(record.getCustomerId());// 客户id
        accountLog.setSeqNo(seqNo);// 请求流水号
        accountLog.setLoanId(record.getLoanId());// 贷款订单id
        accountLog.setAmount(record.getAmount());// 记账金额
        accountLog.setSettleChannel(record.getSettleChannel());// BEPS-小额;HVPS-大额;IBPS-网银清算;
        accountLog.setTransactionId(transactionId);// 交易参考号(核心/支付返回)
        accountLog.setReturnCode(busCode);// 交易返回码
        accountLog.setReturnMsg(busMsg);// 交易返回信息
        accountLog.setReturnStatus(result);// 交易状态
        accountLog.setBusinessDate(businessDate);// 记账日期
        accountLog.setUpdateBy(TransBizConstant.SYS_OPRATE);// 最后更新操作员
        accountLog.setRecordVersionNumber(TransBizConstant.INIT_RECORD_VERSION_NUMBER);// 版本号
        return accountLog;
    }

    /**
     * 构建放款流水记账信息
     * @param record 记账初始化信息
     * @param result 记账状态
     * @return
     */
    private TlDisbursementLog buildTlDisbursementLog(BtDailyAccountList record, String result){
        TlDisbursementLog disbursementLog = new TlDisbursementLog();
        // 主键ID与放款流水表一致
        disbursementLog.setId(record.getId());
        // 日终T24核心汇总记账状态 S-记账成功，F-记账失败，O-记账状态未知，默认D-未记账
        disbursementLog.setKeepAccountStatus(result);
        disbursementLog.setUpdateBy(TransBizConstant.SYS_OPRATE);
        disbursementLog.setRecordVersionNumber(record.getRecordVersionNumber() + 1);
        return disbursementLog;
    }
}
